return;
if (node->perms && node->perms[0].id != conn->id) {
- d = find_domain_by_domid(node->perms[0].id);
- if (d)
- d->nbentry++;
- }
- else if (conn->domain) {
- conn->domain->nbentry++;
+ if (conn->transaction) {
+ transaction_entry_inc(conn->transaction,
+ node->perms[0].id);
+ } else {
+ d = find_domain_by_domid(node->perms[0].id);
+ if (d)
+ d->nbentry++;
+ }
+ } else if (conn->domain) {
+ if (conn->transaction) {
+ transaction_entry_inc(conn->transaction,
+ conn->domain->domid);
+ } else {
+ conn->domain->nbentry++;
+ }
}
}
return;
if (node->perms && node->perms[0].id != conn->id) {
- d = find_domain_by_domid(node->perms[0].id);
- if (d && d->nbentry)
- d->nbentry--;
- } else if (conn->domain && conn->domain->nbentry)
- conn->domain->nbentry--;
+ if (conn->transaction) {
+ transaction_entry_dec(conn->transaction,
+ node->perms[0].id);
+ } else {
+ d = find_domain_by_domid(node->perms[0].id);
+ if (d && d->nbentry)
+ d->nbentry--;
+ }
+ } else if (conn->domain && conn->domain->nbentry) {
+ if (conn->transaction) {
+ transaction_entry_dec(conn->transaction,
+ conn->domain->domid);
+ } else {
+ conn->domain->nbentry--;
+ }
+ }
+}
+
+void domain_entry_fix(unsigned int domid, int num)
+{
+ struct domain *d;
+
+ d = find_domain_by_domid(domid);
+ if (d) {
+ if ((d->nbentry += num) < 0) {
+ eprintf("invalid domain entry number %d",
+ d->nbentry);
+ d->nbentry = 0;
+ }
+ }
}
int domain_entry(struct connection *conn)
#include "list.h"
#include "xenstored_transaction.h"
#include "xenstored_watch.h"
+#include "xenstored_domain.h"
#include "xs_lib.h"
#include "utils.h"
#include "xenstored_test.h"
bool recurse;
};
+struct changed_domain
+{
+ /* List of all changed domains in the context of this transaction. */
+ struct list_head list;
+
+ /* Identifier of the changed domain. */
+ unsigned int domid;
+
+ /* Amount by which this domain's nbentry field has changed. */
+ int nbentry;
+};
+
struct transaction
{
/* List of all transactions active on this connection. */
/* List of changed nodes. */
struct list_head changes;
+
+ /* List of changed domains - to record the changed domain entry number */
+ struct list_head changed_domains;
};
extern int quota_max_transaction;
/* Attach transaction to input for autofree until it's complete */
trans = talloc(in, struct transaction);
INIT_LIST_HEAD(&trans->changes);
+ INIT_LIST_HEAD(&trans->changed_domains);
trans->generation = generation;
trans->tdb_name = talloc_asprintf(trans, "%s.%p",
xs_daemon_tdb(), trans);
void do_transaction_end(struct connection *conn, const char *arg)
{
struct changed_node *i;
+ struct changed_domain *d;
struct transaction *trans;
if (!arg || (!streq(arg, "T") && !streq(arg, "F"))) {
/* Don't close this: we won! */
trans->tdb = NULL;
+ /* fix domain entry for each changed domain */
+ list_for_each_entry(d, &trans->changed_domains, list)
+ domain_entry_fix(d->domid, d->nbentry);
+
/* Fire off the watches for everything that changed. */
list_for_each_entry(i, &trans->changes, list)
fire_watches(conn, i->node, i->recurse);
send_ack(conn, XS_TRANSACTION_END);
}
+void transaction_entry_inc(struct transaction *trans, unsigned int domid)
+{
+ struct changed_domain *d;
+
+ list_for_each_entry(d, &trans->changed_domains, list)
+ if (d->domid == domid) {
+ d->nbentry++;
+ return;
+ }
+
+ d = talloc(trans, struct changed_domain);
+ d->domid = domid;
+ d->nbentry = 1;
+ list_add_tail(&d->list, &trans->changed_domains);
+}
+
+void transaction_entry_dec(struct transaction *trans, unsigned int domid)
+{
+ struct changed_domain *d;
+
+ list_for_each_entry(d, &trans->changed_domains, list)
+ if (d->domid == domid) {
+ d->nbentry--;
+ return;
+ }
+
+ d = talloc(trans, struct changed_domain);
+ d->domid = domid;
+ d->nbentry = -1;
+ list_add_tail(&d->list, &trans->changed_domains);
+}
+
void conn_delete_all_transactions(struct connection *conn)
{
struct transaction *trans;